DeepWiki

04.b - Stripe-Webhook-Handling

Relevant source files

This document details the Stripe webhook endpoint that receives and processes payment events from Stripe's payment processing system. The endpoint is responsible for signature verification, event processing, logging payment details, and dispatching notifications to the ntfy.sh message broker for downstream automation.

For information about creating Stripe checkout sessions, see Stripe Checkout Creation. For details on how payments are linked to GitHub installations, see Payment-to-Installation Linking. For information about the ntfy.sh notification system that receives these webhook notifications, see ntfy Integration & Message Broker.


The Stripe webhook handler is implemented as a Next.js 14 App Router route handler located at app/api/webhooks/stripe/route.ts

It supports three HTTP methods to accommodate different operational requirements.

MethodPurposeResponse
OPTIONSCORS preflight requests200 with CORS headers
GETVerification endpoint"Stripe webhook endpoint is active"
POSTWebhook event processing{received: true} or error

The OPTIONS handler app/api/webhooks/stripe/route.ts L6-L15

enables cross-origin requests from Stripe's webhook delivery system by returning appropriate CORS headers (Access-Control-Allow-Origin: *, Access-Control-Allow-Methods, Access-Control-Allow-Headers).

The GET handler app/api/webhooks/stripe/route.ts L18-L20

provides a simple health check endpoint for verifying that the webhook URL is accessible.

Sources: app/api/webhooks/stripe/route.ts L1-L93


Stripe webhook signature verification is the critical security mechanism that ensures webhook requests originate from Stripe and have not been tampered with during transit.

Diagram: Webhook Signature Verification Flow

The verification process uses the stripe.webhooks.constructEvent() method from the Stripe SDK app/api/webhooks/stripe/route.ts L40

which performs cryptographic validation of the webhook signature against the request body and the STRIPE_WEBHOOK_SECRET environment variable.

// Signature verification code structure (app/api/webhooks/stripe/route.ts:39-44)event = stripe.webhooks.constructEvent(body, signature, webhookSecret)

Sources: app/api/webhooks/stripe/route.ts L22-L44

.env.example L12


The webhook handler processes the checkout.session.completed event type, which Stripe fires when a customer successfully completes payment through Stripe Checkout.

Diagram: checkout.session.completed Event Processing Flow

The handler extracts the following data from the Stripe Checkout Session object app/api/webhooks/stripe/route.ts L49-L59

:

FieldSourcePurpose
session.idSession IDFull session identifier for correlation
session.amount_totalTotal amount in centsPayment amount ($10.00 = 1000)
session.customer_emailCustomer emailPrimary contact information
session.customer_details?.emailFallback emailAlternative email source
session.payment_statusPayment statusConfirmation of successful payment

The handler logs payment details to the server console in a formatted structure app/api/webhooks/stripe/route.ts L51-L59

:

================================================================================
💰 NEW PAYMENT RECEIVED
================================================================================
Session ID: cs_test_abc123...
Amount: $10
Customer Email: user@example.com
Payment Status: paid
Timestamp: 2024-01-15T10:30:45.123Z
================================================================================

This console output appears in Vercel function logs and provides an audit trail for manual payment verification.

Sources: app/api/webhooks/stripe/route.ts L46-L82


After logging the payment, the webhook handler sends a notification to ntfy.sh, which serves as the message broker triggering the automation pipeline that clones customer repositories.

Diagram: ntfy.sh Notification Message Construction

The notification message app/api/webhooks/stripe/route.ts L68

follows this structure:

New GoDeep.wiki Sale!

💰 Amount: $10.00
📧 Customer: user@example.com
🔑 Match ID: abc123def456
⏰ Time: 1/15/2024, 10:30:45 AM

⚠️ Waiting for customer to connect GitHub...
Match this ID with Step 2 notification.

The Match ID is the last 12 characters of the full Stripe session ID app/api/webhooks/stripe/route.ts L67

This shortened identifier serves two purposes:

  1. Manual Correlation: Enables the system owner to match payment notifications with GitHub connection notifications
  2. Size Reduction: Full session IDs (e.g., cs_test_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6) are truncated to m3n4o5p6 for readability

The full session ID is still logged to the console app/api/webhooks/stripe/route.ts L54

and stored in Stripe's dashboard for complete correlation if needed.

The notification is sent via HTTP POST app/api/webhooks/stripe/route.ts L70-L79

:

HeaderValuePurpose
Content-Typetext/plainPlain text message body
TitleStep 1: Payment Received - GoDeep.wikiNotification title
PriorityhighPriority level for client apps
Tagsmoneybag,tadaVisual emoji tags

The ntfy.sh topic is configured via the NTFY_TOPIC environment variable app/api/webhooks/stripe/route.ts L62

with a default value of godeep-wiki-payments if not specified.

Sources: app/api/webhooks/stripe/route.ts L61-L81

.env.example L14


The webhook handler implements a layered error handling strategy to provide clear diagnostics while maintaining security.

ConditionHTTP StatusResponse BodyLogged
Missing stripe-signature header400"Missing stripe-signature header"No
STRIPE_WEBHOOK_SECRET not configured500"Webhook secret not configured"Yes
Invalid webhook signature400"Webhook Error: {message}"Yes
Event processing error500"Error processing webhook"Yes
Successful processing200{"received": true}Yes

Diagram: Error Handling Sequence

The handler uses two nested try-catch blocks app/api/webhooks/stripe/route.ts L39-L91

:

  1. Outer Try-Catch: Captures signature verification failures app/api/webhooks/stripe/route.ts L39-L44
  2. Inner Try-Catch: Captures event processing and ntfy.sh dispatch failures app/api/webhooks/stripe/route.ts L46-L91

All errors are logged to the console using console.error() for debugging and audit purposes.

Sources: app/api/webhooks/stripe/route.ts L39-L92


The webhook handler depends on the following environment variables:

VariablePurposeExampleConfigured In
STRIPE_WEBHOOK_SECRETWebhook signature verificationwhsec_abc123...Stripe Dashboard → Webhooks
NTFY_TOPICntfy.sh notification topicgodeep-wiki-paymentsManual configuration

The STRIPE_WEBHOOK_SECRET is obtained from the Stripe Dashboard when configuring the webhook endpoint. In production, the webhook URL should be set to https://godeep.wiki/api/webhooks/stripe.

To configure this webhook in the Stripe Dashboard:

  1. Navigate to Developers → Webhooks
  2. Click Add endpoint
  3. Enter webhook URL: https://godeep.wiki/api/webhooks/stripe
  4. Select event: checkout.session.completed
  5. Copy the signing secret and set as STRIPE_WEBHOOK_SECRET

Sources: app/api/webhooks/stripe/route.ts L30-L34

.env.example L12-L14

CLAUDE.md L166-L167


The Stripe webhook serves as the first event source in the two-phase notification system that triggers repository cloning automation.

Diagram: Webhook Integration in Two-Phase Notification System

The webhook notification is labeled "Step 1" because it represents the first of two required events:

  1. Step 1: Payment received (this webhook)
  2. Step 2: GitHub repository connected (see OAuth Callback Handler)

Both notifications include the same Match ID (last 12 characters of session_id) to enable manual correlation by the system owner. The automation scripts do not automatically trigger from this webhook alone—they require the Step 2 notification that includes the installation_id.

Sources: app/api/webhooks/stripe/route.ts L68-L78

CLAUDE.md L32-L43

Refresh this wiki

Last indexed: 23 November 2025 (922b35)

On this page

Ask Devin about godeep.wiki-jb

04.b - Stripe-Webhook-Handling | DeepWiki | godeep.wiki